package com.example.teesystem.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.teesystem.common.cache.UserCache;
import com.example.teesystem.common.exception.Assert;
import com.example.teesystem.common.utils.Response;
import com.example.teesystem.common.utils.ResultCode;
import com.example.teesystem.entity.*;
import com.example.teesystem.entity.vo.IssueRecord.IssueRecordInsertVo;
import com.example.teesystem.entity.vo.PageResponseVo;
import com.example.teesystem.entity.vo.dailyIssue.DailyIssueGetVo;
import com.example.teesystem.entity.vo.dailyIssue.DailyIssueSubVo;
import com.example.teesystem.entity.vo.wrongSet.WrongSetSelectVo;
import com.example.teesystem.entity.vo.wrongSet.WrongSetUpdateVo;
import com.example.teesystem.entityDto.AnswerMessage;
import com.example.teesystem.entityDto.IssueList;
import com.example.teesystem.entityDto.IssueMessage;
import com.example.teesystem.entityDto.WrongSetList;
import com.example.teesystem.filter.MyHandlerInterceptor;
import com.example.teesystem.mapper.*;
import com.example.teesystem.service.IssueRecordService;
import com.example.teesystem.service.WrongSetService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* @author NieYaShi
* @description 针对表【t_wrong_set】的数据库操作Service实现
* @createDate 2022-04-07 15:04:19
*/
@Service
@AllArgsConstructor
public class WrongSetServiceImpl extends ServiceImpl<WrongSetMapper, WrongSet>
    implements WrongSetService{

    private final WrongSetMapper wrongSetMapper;
    private final IssueMapper issueMapper;
    private final IssueRecordMapper issueRecordMapper;

    private final IssueRecordService issueRecordService;

    @Override
    public Response insertToWrongSet(Integer issueId) {
        WrongSet wrongSet = new WrongSet();
        wrongSet.setIssueId(issueId);
        wrongSet.setStudentId(MyHandlerInterceptor.getUid());

        Issue issue = issueMapper.selectById(issueId);
        wrongSet.setCourseId(issue.getCourseId());
        WrongSet def = wrongSetMapper.getWrongSetByStuIdAndIssueId(wrongSet.getStudentId(), wrongSet.getIssueId());
        if (def == null){
            int ERROR = -1;
            int id = ERROR;
            wrongSetMapper.insert(wrongSet);
            id = wrongSet.getId();
            if (id == ERROR){
                return Response.error(ResultCode.INSERT_ERROR);
            }else{
                return Response.ok();
            }
        }else {
            return Response.ok();
        }
    }

    @Override
    public PageResponseVo<WrongSetList> getAllWrongSet(WrongSetSelectVo wrongSetSelectVo) {
        Page<WrongSet> page = new Page<>(wrongSetSelectVo.getCur(), wrongSetSelectVo.getSize());
        QueryWrapper<WrongSet> wrapper = new QueryWrapper<>();
        wrapper.eq( "student_id", MyHandlerInterceptor.getUid())
                .eq("course_id", wrongSetSelectVo.getCourseId())
                .orderByDesc("id");
        Page<WrongSet> myPage = this.page(page, wrapper);
        List<WrongSet> wrongSets = myPage.getRecords();
        List<WrongSetList> wrongSetLists = new ArrayList<>();
        for (WrongSet wrongSet : wrongSets){
            WrongSetList wrongSetList = new WrongSetList(wrongSet);

            Issue issue = issueMapper.getIssueMessageById(wrongSet.getIssueId());
            User def = new User();
            def.setMyName("用户未找到");
            IssueMessage issueMessage = new IssueMessage(issue);
            if (issueMessage.getUploadUid() != null){
                User u1 = UserCache.userMap.getOrDefault(issueMessage.getUploadUid(), def);
                issueMessage.setUploadName(u1.getMyName());
            }

            wrongSetList.setIssueMessage(issueMessage);
            wrongSetLists.add(wrongSetList);
        }
        return new PageResponseVo<>(wrongSetLists, myPage.getCurrent(), myPage.getSize(), myPage.getPages());
    }

    @Override
    public Response updateWrongSet(WrongSetUpdateVo wrongSetUpdateVo) {
        try{
            WrongSet wrongSet = wrongSetMapper.selectById(wrongSetUpdateVo.getId());
            if (wrongSet == null) {
                return Response.error(ResultCode.WRONG_SET_ID_ERROR.getMsg(), ResultCode.WRONG_SET_ID_ERROR.getCode());
            }
            int issueId = wrongSetMapper.getIssueIdById(wrongSetUpdateVo.getId());
            Issue issue = issueMapper.selectById(issueId);
            if (issue == null){
                return Response.error(ResultCode.ISSUE_NOT_EXIST_ERROR);
            }
            String realAnswer = issue.getAnswer();
            String studentAnswer = wrongSetUpdateVo.getAnswer();

            IssueRecordInsertVo issueRecordInsertVo = new IssueRecordInsertVo(issueId, studentAnswer);
            issueRecordService.addIssueRecordService(issueRecordInsertVo);

            if (checkAnswer(realAnswer, studentAnswer)) {
                Integer num = wrongSet.getNum();
                num++;
                wrongSet.setNum(num);
                if (num == 3) {
                    wrongSetMapper.autoDeleteWrongSet(wrongSetUpdateVo.getId());
                } else {
                    wrongSetMapper.updateById(wrongSet);
                }

                return Response.ok(new AnswerMessage(issue, true));
            }
            return Response.ok(new AnswerMessage(issue, false));
        }catch (Exception e){
            return Response.error(ResultCode.UPDATE_MESSAGE_ERROR);
        }
    }

    private Boolean checkAnswer(String realAnswer, String studentAnswer){
        String[] realAnswers = realAnswer.toUpperCase().split("\\$");
        String[] studentAnswers = studentAnswer.toUpperCase().split("\\$");

        if (realAnswers.length != studentAnswers.length){
            return false;
        }else {
            List<String> rightAnswer = Arrays.asList(realAnswers);
            boolean judge = true;
            for (String s:studentAnswers){
                if(!rightAnswer.contains(s)){
                    judge = false;
                    break;
                }
            }
            return judge;
        }
    }

    @Override
    public Response deleteWrongSet(Integer id) {
        try{
            wrongSetMapper.deleteWrongSet(id);
            return Response.ok();
        }catch (Exception e){
            return Response.error(ResultCode.UPDATE_MESSAGE_ERROR);
        }
    }
    
    @Override
    public DailyIssueGetVo get(Integer id, Integer courseId) {
        // 如果学生错题本里有题目，则返回错题集里的一道题
        QueryWrapper<WrongSet> wrapper = new QueryWrapper<>();
        wrapper.eq("student_id", id);
        List<WrongSet> wrongSets = this.list(wrapper);
        if(!wrongSets.isEmpty()) {
            Integer issueId = wrongSets.get(RandomUtil.randomInt(0, wrongSets.size())).getIssueId();
            return new DailyIssueGetVo(issueId, true);
        }

        return new DailyIssueGetVo(issueMapper.getIssueByRandomOne(courseId), false);
    }
    
    @Override
    public Boolean sub(DailyIssueSubVo subVo) {
        // 如果每日一题来自错题集，则需要对错题集进行更新
        if(subVo.getIsFromWrongSet()) {
            // 回答正确则 num + 1
            if(subVo.getAnswerRight()) {
                QueryWrapper<WrongSet> wrapper = new QueryWrapper<>();
                wrapper.eq("student_id", MyHandlerInterceptor.getUid())
                        .eq("issue_id", subVo.getIssueId());
                WrongSet wrongSet = wrongSetMapper.selectOne(wrapper);
                wrongSet.setNum(wrongSet.getNum() + 1);
                this.updateById(wrongSet);
                // num = 3 则从错题集中移除
                if(wrongSet.getNum() == 3) {
                    this.removeById(wrongSet);
                }
            } else {
                // 回答错误则 num = 0
                UpdateWrapper<WrongSet> wrapper = new UpdateWrapper<>();
                wrapper.eq("student_id", MyHandlerInterceptor.getUid())
                        .eq("issue_id", subVo.getIssueId())
                        .set("num", 0);
                this.update(wrapper);
            }
        } else {
            // 如果每日一题不是来自错题集且回答错误，则将该题加入到错题集中
            if(!subVo.getAnswerRight()) {
                WrongSet wrongSet = new WrongSet();
                wrongSet.setStudentId(MyHandlerInterceptor.getUid());
                wrongSet.setIssueId(subVo.getIssueId());
                wrongSet.setNum(0);
                this.save(wrongSet);
            }
        }
        
        return true;
    }

    @Override
    public Response getWrongSetByOtherMessage(Integer courseId) {
        try{
            List<Integer> issueIds = issueRecordMapper.getIssueIdByWrongNum(courseId);
            List<Issue> issues = issueMapper.getIssuesByIds(issueIds);
            List<IssueMessage> issueLists = new ArrayList<>();
            for (Issue issue : issues) {
                issueLists.add(new IssueMessage(issue));
            }
            return Response.ok(issueLists);
        }catch (Exception e){
            return Response.error(ResultCode.GET_ERROR);
        }

    }

    @Override
    public void updateWrongSet(Integer issueId) {
        WrongSet wrongSet = new WrongSet();
        wrongSet.setIssueId(issueId);
        wrongSet.setStudentId(MyHandlerInterceptor.getUid());

        Issue issue = issueMapper.selectById(issueId);
        wrongSet.setCourseId(issue.getCourseId());
        WrongSet def = wrongSetMapper.getWrongSetByStuIdAndIssueId(wrongSet.getStudentId(), wrongSet.getIssueId());
        if (def == null){
            int ERROR = -1;
            int id = ERROR;
            wrongSetMapper.insert(wrongSet);
            id = wrongSet.getId();
        }
    }
}
